home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Programming / QuakeTools / src / libqtools / wad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  15.9 KB  |  594 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3.  
  4. /*
  5.  * WAD2-tools
  6.  *
  7.  * entryName    == 0 -> OP_EXTRACT all
  8.  * destDir == 0 -> OP_EXTRACT to current directory
  9.  */
  10.  
  11. /*
  12.  *
  13.  */
  14.  
  15. bool CheckWAD2(FILE * wadFile, struct wadheader * Header, bool newWad)
  16. {
  17.   if (wadFile) {
  18.     fseek(wadFile, 0, SEEK_END);
  19.     if (ftell(wadFile) == 0) {
  20.       if (newWad == TRUE) {
  21.     /*
  22.      * file is new 
  23.      */
  24.     Header->magic.integer = MAGIC_WAD2;
  25.     Header->offset = LittleLong(sizeof(struct wadheader));
  26.  
  27.     Header->numentries = LittleLong(0);
  28.     fwrite(Header, 1, sizeof(struct wadheader), wadFile);
  29.  
  30.     return TRUE;
  31.       }
  32.       else
  33.     return FALSE;
  34.     }
  35.     else {
  36.       fseek(wadFile, 0, SEEK_SET);
  37.       fread(Header, 1, sizeof(struct wadheader), wadFile);
  38.       return Header->magic.integer == MAGIC_WAD2 ? TRUE : FALSE;
  39.     }
  40.   }
  41.   else
  42.     return FALSE;
  43. }
  44.  
  45. /*
  46.  * findwad2 return ever one entry more than exists!
  47.  */
  48. struct wadentry *FindWAD2(FILE * wadFile, char *entryName, struct wadheader *Header, struct wadentry **Entry, filetype wadType)
  49. {
  50.   struct wadentry *allEntries;
  51.  
  52.   fseek(wadFile, LittleLong(Header->offset), SEEK_SET);
  53.   if ((*Entry = allEntries = (struct wadentry *)tmalloc((LittleLong(Header->numentries) + 1) * sizeof(struct wadentry)))) {
  54.     int i;
  55.  
  56.     fread(allEntries, 1, (LittleLong(Header->numentries)) * sizeof(struct wadentry), wadFile);
  57.  
  58.     if (entryName) {
  59.       for (i = 0; i < LittleLong(Header->numentries); i++) {
  60.     if (!strncasecmp(entryName, allEntries->name, NAMELEN_WAD)) {
  61.       // deactivated cause of complications
  62.       //if ((allEntries->type == wadType) || (wadType == TYPE_UNKNOWN)) {
  63.       /*
  64.        * return offset of valid entry 
  65.        */
  66.       return allEntries;
  67.       //}
  68.     }
  69.     allEntries++;
  70.       }
  71.     }
  72.     /*
  73.      * not in wadFile 
  74.      */
  75.     return 0;
  76.   }
  77.   else
  78.     return (struct wadentry *)-1;
  79. }
  80.  
  81. struct wadentry *SearchWAD2(char *entryName, struct wadheader *Header, struct wadentry *allEntries, filetype wadType) {
  82.   int i;
  83.  
  84.   for (i = 0; i < LittleLong(Header->numentries); i++) {
  85.     if (!strncasecmp(entryName, allEntries->name, NAMELEN_WAD))
  86.       return allEntries;
  87.     allEntries++;
  88.   }
  89.   return 0;
  90. }
  91.  
  92. struct palpic *GetWAD2Picture(FILE *wadFile, struct wadentry *Entry)
  93. {
  94.   struct palpic *Picture = 0;
  95.  
  96.   fseek(wadFile, LittleLong(Entry->offset), SEEK_SET);
  97.  
  98.   switch (Entry->type) {
  99.     case WAD2_PALETTE:
  100.       /*
  101.        * there MUST be only one palette in the wad, which is exactly the one we took above
  102.        */
  103.       if ((Picture = pmalloc(16, 16, 0, Entry->name))) {
  104.     short int i;
  105.  
  106.     for (i = 0; i < 256; i++)
  107.       Picture->rawdata[i] = (unsigned char)i;
  108.       }
  109.       break;
  110.     case WAD2_STATUSBAR:
  111.     case WAD2_CONPIC:
  112.       switch (Entry->compr) {
  113.     case CMP_NONE:
  114.     case CMP_MIP0:
  115.       Picture = GetLMP(wadFile, Entry->name);
  116.       break;
  117.     case CMP_LZ77:
  118.     case (CMP_LZ77 | CMP_MIP0):{
  119.         struct lump *Lump;
  120.  
  121.         if ((Lump = (struct lump *)GetLZ77(wadFile, LittleLong(Entry->wadsize)))) {
  122.           Picture = ParseLMP(Lump, Entry->name);
  123.           tfree(Lump);
  124.         }
  125.       }
  126.       break;
  127.     default:
  128.       break;
  129.       }
  130.       break;
  131.     case WAD2_MIPMAP:
  132.     case 0:
  133.       /*
  134.        * fix me!!! this is bogus 
  135.        */
  136.       switch (Entry->compr) {
  137.     case CMP_NONE:
  138.     case CMP_MIP0:
  139.       Picture = GetMipMap(wadFile, MIPMAP_0);
  140. #ifdef DEBUG
  141.       mprintf("get first 4 bytes %x%x%x%x (%x%x%x,%x%x%x,%x%x%x)\n", Picture->rawdata[0], Picture->rawdata[1], Picture->rawdata[2], Picture->rawdata[3],
  142.           Picture->palette[0].r, Picture->palette[0].g, Picture->palette[0].b,
  143.           Picture->palette[1].r, Picture->palette[1].g, Picture->palette[1].b,
  144.           Picture->palette[2].r, Picture->palette[2].g, Picture->palette[2].b);
  145. #endif
  146.       break;
  147.     case CMP_LZ77:
  148.     case (CMP_LZ77 | CMP_MIP0):{
  149.         struct mipmap *MipMap;
  150.  
  151.         if ((MipMap = (struct mipmap *)GetLZ77(wadFile, LittleLong(Entry->wadsize)))) {
  152.           Picture = ParseMipMap(MipMap, MIPMAP_0);
  153.           tfree(MipMap);
  154.         }
  155.       }
  156.       break;
  157.     default:
  158.       break;
  159.       }
  160.       break;
  161.     default:
  162.       break;
  163.   }
  164.   return Picture;
  165. }
  166.  
  167. struct rawdata *GetWAD2Raw(FILE *wadFile, struct wadentry *Entry)
  168. {
  169.   struct rawdata *rawData = 0;
  170.  
  171.   fseek(wadFile, LittleLong(Entry->offset), SEEK_SET);
  172.  
  173.   switch (Entry->compr) {
  174.     case CMP_NONE:
  175.       rawData = GetRaw(wadFile, Entry->name, LittleLong(Entry->wadsize));
  176.       break;
  177.     case CMP_MIP0:{
  178.     struct palpic *MipMap;
  179.  
  180.     if ((MipMap = GetMipMap(wadFile, MIPMAP_0))) {
  181.       if ((rawData = rmalloc(MIP_MULT(LittleLong(MipMap->width) * LittleLong(MipMap->height)) + sizeof(struct mipmap), Entry->name))) {
  182.         PasteMipMap((struct mipmap *)rawData->rawdata, MipMap);
  183.       }
  184.       pfree(MipMap);
  185.     }
  186.       }
  187.       break;
  188.     case CMP_LZ77:{
  189.     char *Data;
  190.  
  191.     if ((Data = GetLZ77(wadFile, LittleLong(Entry->wadsize)))) {
  192.       rawData = ParseRaw(Data, Entry->name, LittleLong(Entry->memsize));
  193.       tfree(Data);
  194.     }
  195.       }
  196.       break;
  197.     case (CMP_LZ77 | CMP_MIP0):{
  198.     struct mipmap *GetMip;
  199.     struct palpic *MipMap;
  200.  
  201.     if ((GetMip = (struct mipmap *)GetLZ77(wadFile, LittleLong(Entry->wadsize)))) {
  202.       if ((MipMap = ParseMipMap(GetMip, MIPMAP_0))) {
  203.         if ((rawData = rmalloc(MIP_MULT(LittleLong(MipMap->width) * LittleLong(MipMap->height)) + sizeof(struct mipmap), Entry->name))) {
  204.           PasteMipMap((struct mipmap *)rawData->rawdata, MipMap);
  205.         }
  206.         pfree(MipMap);
  207.       }
  208.       tfree(GetMip);
  209.     }
  210.       }
  211.       break;
  212.     default:
  213.       break;
  214.   }
  215.  
  216.   return rawData;
  217. }
  218.  
  219. bool ExtractWAD2(FILE * wadFile, FILE * script, char *destDir, char *entryName, unsigned char outType, operation procOper, filetype wadType)
  220. {
  221.   struct wadheader Header;
  222.   struct wadentry *Entry, *allEntries;
  223.   struct rgb *oldCache = cachedPalette;
  224.   bool retval = FALSE;
  225.  
  226.   if (CheckWAD2(wadFile, &Header, FALSE) == TRUE) {
  227.     /*
  228.      * we assume that the dir is at the end of the file!!!!! 
  229.      */
  230.     switch ((int)(Entry = FindWAD2(wadFile, entryName, &Header, &allEntries, wadType))) {
  231.       case -1:
  232.     eprintf("cannot tmalloc memory for all entries of size %ld\n", (LittleLong(Header.numentries) + 1) * sizeof(struct wadentry));
  233.  
  234.     break;
  235.       case 0:
  236.     if ((entryName) && (*entryName != '\0') && (outType != TYPE_WAD2)) {
  237.       eprintf("no entry %s found in wad\n", entryName);
  238.       break;
  239.     }
  240.       default:{
  241.       struct rgb *Palette = 0;
  242.       bool ownPalette = FALSE;
  243.       int i = 0;
  244.  
  245.       if (outType != TYPE_NONE) {
  246.         /*
  247.          * first search for a palette in the wad-file and use that instead of default palette 
  248.          */
  249.         struct wadentry *palEntry = allEntries;
  250.  
  251.         for (i = 0; i < LittleLong(Header.numentries); i++) {
  252.           if (palEntry->type == WAD2_PALETTE) {
  253.         fseek(wadFile, LittleLong(palEntry->offset), SEEK_SET);
  254.         switch (palEntry->compr) {
  255.           case CMP_NONE:
  256.           case CMP_MIP0:
  257.             if ((Palette = (struct rgb *)tmalloc(256 * 3)))
  258.               fread(Palette, 1, 256 * 3, wadFile);
  259.             break;
  260.           case CMP_LZ77:
  261.           case (CMP_LZ77 | CMP_MIP0):
  262.             Palette = (struct rgb *)GetLZ77(wadFile, LittleLong(palEntry->wadsize));
  263.             break;
  264.           default:
  265.             break;
  266.         }
  267.         mprintf("use wads built-in palette\n");
  268.         ownPalette = TRUE;
  269.         break;
  270.           }
  271.           palEntry++;
  272.         }
  273.         i = 0;
  274.         /*
  275.          * we take the new palette for conversions
  276.          */
  277.         if (!Palette)
  278.           Palette = GetPalette();
  279.         else
  280.           cachedPalette = Palette;
  281.       }
  282.  
  283.       /*
  284.        * process only ONE
  285.        */
  286.       if (Entry && (outType != TYPE_WAD2))
  287.         i = LittleLong(Header.numentries) - 1;
  288.       /*
  289.        * reset and process ALL
  290.        */
  291.       else
  292.         Entry = allEntries;
  293.  
  294.       for (; i < LittleLong(Header.numentries); i++) {
  295.         char fileName[NAMELEN_PATH];
  296.  
  297.         strncpy(fileName, destDir, NAMELEN_PATH - 1);
  298.         strncat(fileName, Entry->name, NAMELEN_PATH - 1);
  299.  
  300.         switch (outType) {
  301.           case TYPE_PPM:    strncat(fileName, ".ppm", NAMELEN_PATH - 1); break;
  302.           case TYPE_JPEG:    strncat(fileName, ".jpg", NAMELEN_PATH - 1); break;
  303.           case TYPE_ILBM:    strncat(fileName, ".iff", NAMELEN_PATH - 1); break;
  304.           case TYPE_PNG:    strncat(fileName, ".png", NAMELEN_PATH - 1); break;
  305.           case TYPE_WAD2:    strncat(fileName, ".wad", NAMELEN_PATH - 1); break;
  306.           case TYPE_NONE:
  307.           default:
  308.         switch (Entry->type) {
  309.           case WAD2_PALETTE:    strncat(fileName, ".pal", NAMELEN_PATH - 1); outType = TYPE_NONE; break;
  310.           case WAD2_STATUSBAR:    strncat(fileName, ".stb", NAMELEN_PATH - 1); outType = TYPE_LUMP; break;
  311.           case WAD2_MIPMAP:    strncat(fileName, ".mip", NAMELEN_PATH - 1); outType = TYPE_MIPMAP; break;
  312.           case WAD2_CONPIC:    strncat(fileName, ".lmp", NAMELEN_PATH - 1); outType = TYPE_LUMP; break;
  313.           default:        strncat(fileName, ".xxx", NAMELEN_PATH - 1); outType = TYPE_NONE; break;
  314.         }
  315.         break;
  316.         }
  317.  
  318.         switch (procOper) {
  319.           case OP_EXTRACT:{
  320.           if (outType == TYPE_WAD2) {
  321.             struct rawdata *rawData;
  322.  
  323.             mprintf("extract %s to %s ...\n", Entry->name, entryName);
  324.             if ((rawData = GetWAD2Raw(wadFile, Entry))) {
  325.               retval = AddWAD2(0, rawData, entryName, OP_ADD, Entry->type);
  326.               rfree(rawData);
  327.             }
  328.           }
  329.           else {
  330.             FILE *fileDst;
  331.  
  332.             mprintf("extract %s to %s ...\n", Entry->name, fileName);
  333.             CreatePath(fileName);
  334.             if ((fileDst = fopen(fileName, WRITE_BINARY))) {
  335.               if (outType == TYPE_NONE) {
  336.                 struct rawdata *rawData;
  337.  
  338.                 if ((rawData = GetWAD2Raw(wadFile, Entry))) {
  339.               retval = PutRaw(fileDst, rawData);
  340.               rfree(rawData);
  341.                 }
  342.               }
  343.               else if (outType != TYPE_NONE) {
  344.                 struct palpic *Picture;
  345.  
  346.                 if ((Picture = GetWAD2Picture(wadFile, Entry))) {
  347.                   switch (outType) {
  348.                     case TYPE_LUMP:    retval = PutLMP(fileDst, Picture);            break;
  349.                     case TYPE_MIPMAP:    retval = PutMipMap(fileDst, Picture);         break;
  350.                     default:        retval = PutImage(fileDst, Picture, outType); break;
  351.                   }
  352.               pfree(Picture);
  353.                 }
  354.               }
  355.               fclose(fileDst);
  356.             }
  357.             else
  358.               eprintf("cannot open %s\n", fileName);
  359.           }
  360.         }
  361.         break;
  362.           case OP_LIST:
  363.           case OP_DEFAULT:
  364.           default:{
  365.           mprintf("%16s %8d bytes (offset: %8x, type: %c, compr: %1d)\n", Entry->name, LittleLong(Entry->wadsize), LittleLong(Entry->offset), Entry->type, (int)Entry->compr);
  366.           retval = TRUE;
  367.         }
  368.         break;
  369.         }
  370.         if (script)
  371.           fprintf(script, "update %s as %s as %c\n", fileName, Entry->name, Entry->type);
  372.         Entry++;
  373.       }
  374.     }
  375.     break;
  376.     }
  377.     tfree(allEntries);
  378.   }
  379.   else
  380.     eprintf("no valid wadfile\n");
  381.  
  382.   cachedPalette = oldCache;
  383.   return retval;
  384. }
  385.  
  386. bool AddWAD2(struct palpic *inPic, struct rawdata *inData, char *wadName, operation procOper, filetype wadType)
  387. {
  388.   char *procName;
  389.   FILE *wadFile = fopen(wadName, READWRITE_BINARY_OLD);
  390.   struct wadheader Header;
  391.   struct wadentry *Entry, *allEntries;
  392.   bool retval = FALSE;
  393.  
  394.   if (!wadFile)
  395.     wadFile = fopen(wadName, READWRITE_BINARY_NEW);
  396.  
  397.   if (wadFile) {
  398.     if (CheckWAD2(wadFile, &Header, TRUE) == TRUE) {
  399.       if (inPic) {
  400.     procName = inPic->name;
  401.       }
  402.       else if (inData) {
  403.     procName = inData->name;
  404.       }
  405.       /*
  406.        * we assume that the dir is at the end of the file!!!!! 
  407.        */
  408.       switch ((int)(Entry = FindWAD2(wadFile, procName, &Header, &allEntries, wadType))) {
  409.     case -1:
  410.       eprintf("cannot tmalloc memory for all entries of size %ld\n", LittleLong(Header.numentries) * sizeof(struct wadentry));
  411.       break;
  412.     case 0:
  413.       switch (procOper) {
  414.         case OP_REPLACE:
  415.           eprintf("no entry %s found to replace in wad %s\n", procName, wadName);
  416.           break;
  417.         case OP_ADD:
  418.         case OP_UPDATE:
  419.         case OP_DEFAULT:
  420.         default:
  421.           fseek(wadFile, LittleLong(Header.offset), SEEK_SET);
  422.           /*
  423.            * seek to end of data and write data
  424.            */
  425.           Entry = allEntries + LittleLong(Header.numentries);
  426.           Entry->offset = Header.offset;
  427.  
  428.           mprintf("add %s to %s ...\n", Entry->name ? Entry->name : procName, wadName);
  429.           if (inData) {
  430.         switch (Compression) {
  431.           case CMP_NONE:
  432.           case CMP_MIP0:
  433.             retval = PutRaw(wadFile, inData);
  434.             break;
  435.           case CMP_LZ77:
  436.           case (CMP_MIP0 | CMP_LZ77):{
  437.               retval = PutLZ77(wadFile, (char *)inData->rawdata, inData->size) > ERROR ? TRUE : FALSE;
  438.               Entry->memsize = LittleLong(inData->size);
  439.             }
  440.             break;
  441.           default:
  442.             break;
  443.         }
  444.           }
  445.           else if (inPic) {
  446.         switch (wadType) {
  447.           case WAD2_PALETTE:
  448.             switch (Compression) {
  449.               case CMP_NONE:
  450.               case CMP_MIP0:
  451.             if (fwrite(inPic->palette, 1, 256 * 3, wadFile) == (256 * 3)) {
  452.               retval = TRUE;
  453.             }
  454.             break;
  455.               case CMP_LZ77:
  456.               case (CMP_MIP0 | CMP_LZ77):{
  457.               retval = PutLZ77(wadFile, (char *)inPic->palette, (256 * 3)) > ERROR ? TRUE : FALSE;
  458.               Entry->memsize = LittleLong(256 * 3);
  459.             }
  460.             break;
  461.               default:
  462.             break;
  463.             }
  464.             break;
  465.           case WAD2_MIPMAP:
  466.             switch (Compression) {
  467.               case CMP_NONE:
  468.             retval = PutMipMap(wadFile, inPic);
  469.             break;
  470.               case CMP_MIP0:
  471.             retval = PutMipMap0(wadFile, inPic);
  472.             break;
  473.               case CMP_LZ77:{
  474.               struct mipmap *MipMap;
  475.  
  476.               if ((MipMap = (struct mipmap *)tmalloc(MIP_MULT(inPic->width * inPic->height) + sizeof(struct mipmap)))) {
  477.                 if ((retval = PasteMipMap(MipMap, inPic)) == TRUE) {
  478.                   retval = PutLZ77(wadFile, (char *)MipMap, MIP_MULT(inPic->width * inPic->height) + sizeof(struct mipmap)) > ERROR ? TRUE : FALSE;
  479.                   Entry->memsize = LittleLong(MIP_MULT(inPic->width * inPic->height) + sizeof(struct mipmap));
  480.                 }
  481.                 tfree(MipMap);
  482.               }
  483.             }
  484.             break;
  485.               case (CMP_MIP0 | CMP_LZ77):{
  486.               struct mipmap *MipMap;
  487.  
  488.               if ((MipMap = (struct mipmap *)tmalloc((inPic->width * inPic->height) + sizeof(struct mipmap)))) {
  489.                 if ((retval = PasteMipMap0(MipMap, inPic)) == TRUE) {
  490.                   retval = PutLZ77(wadFile, (char *)MipMap, (inPic->width * inPic->height) + sizeof(struct mipmap)) > ERROR ? TRUE : FALSE;
  491.                   Entry->memsize = LittleLong((inPic->width * inPic->height) + sizeof(struct mipmap));
  492.                 }
  493.                 tfree(MipMap);
  494.               }
  495.             }
  496.             break;
  497.               default:
  498.             break;
  499.             }
  500.             break;
  501.           case WAD2_STATUSBAR:
  502.           case WAD2_CONPIC:
  503.             switch (Compression) {
  504.               case CMP_NONE:
  505.               case CMP_MIP0:
  506.             retval = PutLMP(wadFile, inPic);
  507.             break;
  508.               case CMP_LZ77:
  509.               case (CMP_MIP0 | CMP_LZ77):{
  510.               struct lump *Lump;
  511.  
  512.               if ((Lump = (struct lump *)tmalloc((inPic->width * inPic->height) + sizeof(struct lump)))) {
  513.                 if ((retval = PasteLMP(Lump, inPic)) == TRUE) {
  514.                   retval = PutLZ77(wadFile, (char *)Lump, (inPic->width * inPic->height) + sizeof(struct lump)) > ERROR ? TRUE : FALSE;
  515.                   Entry->memsize = LittleLong(MIP_MULT(inPic->width * inPic->height) + sizeof(struct lump));
  516.                 }
  517.                 tfree(Lump);
  518.               }
  519.             }
  520.             break;
  521.               default:
  522.             break;
  523.             }
  524.             break;
  525.           default:
  526.             break;
  527.         }
  528.           }
  529.           else
  530.         eprintf("nothing to add\n");
  531.  
  532.           if (retval == TRUE) {
  533.         Entry->wadsize = LittleLong(ftell(wadFile) - LittleLong(Header.offset));
  534.         if ((Entry->compr = Compression) == CMP_NONE)
  535.           Entry->memsize = Entry->wadsize;
  536.         Entry->type = wadType;
  537.         strncpy(Entry->name, procName, NAMELEN_WAD);
  538.         Header.numentries = LittleLong(LittleLong(Header.numentries) + 1);
  539.         Header.offset = LittleLong(ftell(wadFile));
  540.         /*
  541.          * write directory
  542.          */
  543.         if (fwrite(allEntries, 1, LittleLong(Header.numentries) * sizeof(struct wadentry), wadFile) == (LittleLong(Header.numentries) * sizeof(struct wadentry))) {
  544.           fseek(wadFile, 0, SEEK_SET);
  545.           /*
  546.            * write header
  547.            */
  548.           fwrite(&Header, 1, sizeof(struct wadheader), wadFile);
  549.  
  550.           fflush(wadFile);
  551.         }
  552.         else {
  553.           eprintf("cannot write full data to wad %s\n", wadName);
  554.           retval = FALSE;
  555.         }
  556.           }
  557.           else
  558.         eprintf("cannot write data %c %s to wad %s\n", wadType, procName, wadName);
  559.           break;
  560.       }
  561.       tfree(allEntries);
  562.       break;
  563.     default:
  564.       switch (procOper) {
  565.         case OP_REPLACE:
  566.         case OP_UPDATE:
  567.           /*
  568.            * DeleteWAD2() 
  569.            */
  570.           /*
  571.            * AddWAD2() 
  572.            */
  573.           retval = TRUE;
  574.           break;
  575.         case OP_ADD:
  576.         case OP_DEFAULT:
  577.         default:
  578.           eprintf("old entry %s found in wad %s\n", procName, wadName);
  579.           break;
  580.       }
  581.       tfree(allEntries);
  582.       break;
  583.       }
  584.       fclose(wadFile);
  585.     }
  586.     else
  587.       eprintf("no valid wadfile %s\n", wadName);
  588.   }
  589.   else
  590.     eprintf("cannot open desired wadfile %s\n", wadName);
  591.  
  592.   return retval;
  593. }
  594.